/*
Given inorder and postorder traversal of a tree, construct the binary tree.

Note:
You may assume that duplicates do not exist in the tree.
*/

/**
 * Definition for binary tree
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode *buildTree(vector<int> &inorder, vector<int> &postorder) {
        int n = postorder.size();
        if (!n) return NULL;
        unordered_map<int, int>imap;
        buildIndexMap(inorder, imap);
        return buildTreeHelper(n, n-1, postorder, n-1, inorder, imap);        
    }
private:
    void buildIndexMap(vector<int> &inorder, unordered_map<int, int> &imap) {
        for (int i = 0; i < inorder.size(); i++) imap.insert(make_pair(inorder[i], i));
    }
    TreeNode *buildTreeHelper(int n, int poffset, vector<int> &postorder,
        int ioffset, vector<int> &inorder, unordered_map<int, int> &imap) 
    {
        if (!n) return NULL;
        int val = postorder[poffset];
        TreeNode *root = new TreeNode(val);
        int pos = (imap.find(val))->second;
        int newright = ioffset - pos;
        // right subtree
        root->right = buildTreeHelper(newright, poffset-1, postorder, ioffset, inorder, imap);
        // left subtree
        root->left = buildTreeHelper(n-(newright+1), poffset-1-newright, postorder, ioffset-(newright+1), inorder, imap);
        return root;
    }    
};
